package cn.virens.common.project.base.utils.tree;

import cn.virens.common.util.core.Assert;
import cn.virens.common.util.core.stream.StreamUtil;
import cn.virens.common.util.exception.APIException;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.text.StrUtil;

import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class TreeUtil {
    public static final String ROOT = "root";

    public static final String PREFIX = "root:_ROOT_";

    /**
     * 将普通数据列表转换为相应的层级数据结构
     *
     * @param <T>
     * @param list 封装数据列表
     * @return
     * @throws APIException
     */
    public static <T extends TreeNode<T>> List<T> tree(List<T> list) throws APIException {
        return tree(ROOT, list);
    }

    /**
     * 将普通数据列表转换为相应的层级数据结构
     *
     * @param <S>
     * @param <T>
     * @param list 封装数据列表
     * @return
     * @throws APIException
     */
    public static <S, T extends TreeNode<T>> List<T> tree(List<S> list, Function<S, T> fun) throws APIException {
        return tree(ROOT, CollUtil.map(list, fun, true));
    }

    /**
     * 将普通数据列表转换为相应的层级数据结构
     *
     * @param <T>
     * @param parent 上级编号值
     * @param list   封装数据列表
     * @return
     * @throws APIException
     */
    public static <T extends TreeNode<T>> List<T> tree(String parent, List<T> list) throws APIException {
        return StreamUtil.parallelStream(Assert.isNull(list)).filter(a -> {
            return a != null && StrUtil.equals(a.getPkey(), parent);
        }).peek(a -> c(a, list)).collect(Collectors.toList());
    }

    private static <T extends TreeNode<T>> void c(T item, List<T> list) throws APIException {
        item.setChildren(tree(item.getKey(), list));
    }
}
